use anyhow::{Result, anyhow};
use regex::Regex;

pub struct IdCardParser<'a> {
    id: &'a str,
}

impl<'a> IdCardParser<'a> {
    pub fn new(id: &'a str) -> Self {
        Self { id }
    }
    
    pub fn get_birth_year(&self) -> Result<u32> {
        let re = Regex::new(r"^\d{6}(\d{4})")?;
        
        if let Some(caps) = re.captures(self.id) {
            let year = caps.get(1)
                .ok_or_else(|| anyhow!("无法提取年份"))?
                .as_str();
                
            Ok(year.parse()?)
        } else {
            Err(anyhow!("身份证格式错误"))
        }
    }
    
    pub fn validate(&self) -> Result<bool> {
        // 1. 长度检查
        if self.id.len() != 18 {
            return Ok(false);
        }
        
        // 2. 格式检查
        let re = Regex::new(r"^\d{17}[\dXx]$")?;
        if !re.is_match(self.id) {
            return Ok(false);
        }
        
        // 3. 校验码检查
        let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        let check_codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
        
        let sum: usize = self.id[..17]
            .chars()
            .enumerate()
            .map(|(i, c)| c.to_digit(10).unwrap() as usize * weights[i])
            .sum();
            
        let check = check_codes[sum % 11];
        
        Ok(check == self.id.chars().last().unwrap().to_ascii_uppercase())
    }
} 